﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using BigEaterCh.Kontrolki;
using BigEaterCh.Formularze;
using LibreOfficeExport;

namespace BigEaterCh
{
  public partial class FormRozliczenie : FormZywienie
  {
    delegate void DummyDelegate();

    private DateTime _activeDay;

    public DateTime ActiveDay
    {
      get
      {
        return _activeDay;
      }
      set
      {
        _activeDay = value;
        userDzien1.ActiveDay = dateTimePicker1.Value;
        dateTimePicker1.Value = value;
        RefreshDataPrzychody();
        RefreshDataRozchody();
        RefreshDataStan();
        RefreshRozliczenie();
        Przelicz();
      }
    }

    private static FormRozliczenie _instance;

    public static FormRozliczenie Pokaz(Form parentForm)
    {
      if( _instance != null )
      {
        _instance.RefreshDataPrzychody();
        _instance.RefreshDataRozchody();
        _instance.RefreshDataStan();
        _instance.RefreshRozliczenie();
        _instance.Przelicz();
      }
      else
      {
        _instance = new FormRozliczenie
        {
          MdiParent = parentForm
        };
      }
      return _instance;
    }


    /// <summary>
    /// 
    /// </summary>
    private FormRozliczenie()
    {
      InitializeComponent();
      ActiveDay = DateTime.Today;

      this.dataGridViewTextBoxColumn2.DisplayMember = "Description";
      this.dataGridViewTextBoxColumn18.DisplayMember = "Description";
      this.dataGridViewTextBoxColumn21.DisplayMember = "Description";
    }

    /// <summary>
    /// 
    /// </summary>
    private void DateTimePicker1ValueChanged(object sender, EventArgs e)
    {
      ActiveDay = dateTimePicker1.Value;
    }

    /// <summary>
    /// 
    /// </summary>
    private void ButtonDzienPoprzedniClick(object sender, EventArgs e)
    {
      ActiveDay = dateTimePicker1.Value.AddDays(-1);
    }

    /// <summary>
    /// 
    /// </summary>
    private void ButtonDzienNastepnyClick(object sender, EventArgs e)
    {
      ActiveDay = dateTimePicker1.Value.AddDays(1);
    }

    /// <summary>
    /// 
    /// </summary>
    private void TabControl2SelectedIndexChanged(object sender, EventArgs e)
    {
      RefreshDataPrzychody();
      RefreshDataRozchody();
      RefreshDataStan();
      RefreshRozliczenie();
      Przelicz();
    }

    /// <summary>
    /// 
    /// </summary>
    public void RefreshDataPrzychody()
    {
      var query = from c in FormBigEaterCh.Ze.Przychody
                   where c.Data == _activeDay 
                    select c;

      przychodyBindingSource.DataSource = query;
      produktyBindingSource.DataSource = FormBigEaterCh.Ze.Produkty;
      wzBindingSource.DataSource = FormBigEaterCh.Ze.Wz;
      fakturyBindingSource.DataSource = FormBigEaterCh.Ze.Faktury;
    }

    /// <summary>
    /// 
    /// </summary>
    public void RefreshDataRozchody()
    {
      var query = from c in FormBigEaterCh.Ze.Rozchody
                  where c.Data == _activeDay
                  select c;

      rozchodyBindingSource.DataSource = query;
      produktyBindingSource.DataSource = FormBigEaterCh.Ze.Produkty;
    }

    /// <summary>
    /// 
    /// </summary>
    public void RefreshRozliczenie()
    {

      var query = from c in FormBigEaterCh.Ze.Dni
                  where c.Data == _activeDay
                  select c;
      dniBindingSource.DataSource = query;
      typyPosilkowBindingSource.DataSource = FormBigEaterCh.Ze.TypyPosilkow;

    }

    /// <summary>
    /// 
    /// </summary>
    private void Przelicz()
    {
      var s = from c in FormBigEaterCh.Ze.Rozchody
              where c.Data == this._activeDay
              select c;
      decimal sum=0.0m;
      foreach(var c in s)
      {
        sum += c.Wartosc;
      }

      this.textBoxSumaRozchodow.Text = sum.ToString("C2");

      var sumOsoby = (from c in FormBigEaterCh.Ze.Dni
                      where c.Data == this._activeDay
                      select c.IloscPersonelu).Sum();
      var sumDzieci = ( from c in FormBigEaterCh.Ze.Dni
                        where c.Data == this._activeDay
                        select c.IloscDzieci ).Sum();

      var liczbaPos =  (sumDzieci.HasValue?sumDzieci.Value:0 )+ (sumOsoby.HasValue?sumOsoby.Value:0 );
      if( liczbaPos!=0 )
      {
        decimal posJedn = sum/liczbaPos;
        this.textBoxLiczbaPosilkow.Text = liczbaPos.ToString();
        this.textBoxCenaPosilku.Text = posJedn.ToString("C2");
      }
      else
      {
        this.textBoxLiczbaPosilkow.Text = @"Brak posiłków!";
        this.textBoxCenaPosilku.Text = @"Brak posiłków!";
      }
    }

    /// <summary>
    /// 
    /// </summary>
    void RefreshDataStan()
    {
      dniProduktyBindingSource.DataSource = from c in FormBigEaterCh.Ze.DniProdukty
                                            where ( c.Data == _activeDay)
                                            select c;
    }

    /// <summary>
    /// 
    /// </summary>
    private void PrzeliczNastępne()
    {
      var updlQuery = from c in FormBigEaterCh.Ze.DniProdukty
                      where ( c.Data > _activeDay )
                      orderby c.Data ascending
                      select c.Data;

      if( updlQuery.Count()>0 )
      {
        var distq = updlQuery.Distinct();

        Invoke((DummyDelegate) delegate
                                 {
                                   toolStripStatusLabel1.Text = "Przeliczam następne dni";
                                   toolStripProgressBar1.Minimum = 0;
                                   toolStripProgressBar1.Value = 0;
                                   toolStripProgressBar1.Maximum = distq.Count();
                                   toolStripProgressBar1.Visible = false;
                                 });


        foreach( var date in distq )
        {
          RefreshDataStanDate(date);
          Invoke((DummyDelegate) delegate
                                   {
                                     toolStripProgressBar1.Value++;
                                   });
        }

        Invoke((DummyDelegate) delegate
        {
          toolStripStatusLabel1.Text = "";
          toolStripProgressBar1.Value = 0;
          toolStripProgressBar1.Visible = true;
        });


      }
    }

    /// <summary>
    /// 
    /// </summary>
    void EksportRozliczenie(DateTime dt, List<Rozliczenie> lista,out RozliczeniePosilki pos)
    {
      pos = null;
      //try
      //{
      FormBigEaterCh.GetDataBase();
      if( FormBigEaterCh.Ze != null )
      {
        pos = new RozliczeniePosilki();
        //ilość sztuk przychody pomiędzy ostatnim rozliczneniem a obecnym włącznie  produktu w cenie pozycji
        var roz = from c in FormBigEaterCh.Ze.Dni
                  join o in FormBigEaterCh.Ze.TypyPosilkow on c.IdPosilku equals o.IdTypuPosilku
                  where
                    (c.Data == _activeDay)
                  select new
                           {
                             c.IloscDzieci,
                             c.IloscPersonelu,
                             o.Nazwa
                           };

        foreach(var poislek in roz)
        {
          if( string.Compare(poislek.Nazwa ,"Śniadanie",true)==0 )
          {
            pos.SniadanieD = poislek.IloscDzieci.HasValue?poislek.IloscDzieci.Value:0;
            pos.SniadanieP = poislek.IloscPersonelu.HasValue?poislek.IloscPersonelu.Value:0;
          }
          else if( string.Compare(poislek.Nazwa ,"Obiad",true)==0 )
          {
            pos.ObiadD = poislek.IloscDzieci.HasValue?poislek.IloscDzieci.Value:0;
            pos.ObiadP = poislek.IloscPersonelu.HasValue?poislek.IloscPersonelu.Value:0;
          }
          else if( string.Compare(poislek.Nazwa, "Podwieczorek", true)==0 )
          {
            pos.PodwieczorekD = poislek.IloscDzieci.HasValue?poislek.IloscDzieci.Value:0;
            pos.PodwieczorekP = poislek.IloscPersonelu.HasValue?poislek.IloscPersonelu.Value:0;
          }
        }

        //pobieram wszystkie przychody
        var query2 = (from c in FormBigEaterCh.Ze.Przychody
                      join o in FormBigEaterCh.Ze.Produkty on c.IdProduktu equals o.IdProduktu
                      orderby o.GrupyProduktow
                      orderby o.Nazwa
                      select new
                               {
                                 c.IdProduktu,
                                 o.GrupyProduktow,
                                 o.Nazwa,
                                 o.Jednostka,
                                 c.CenaBrutto
                               }).Distinct();

        DateTime? startData = null;
        DateTime? stopData = dt;

        //szukam daty poprzedniej
        var query = from c in FormBigEaterCh.Ze.DniProdukty
                    where (c.Data < dt)
                    select c.Data;
        if (query.Count() > 0) //są jakieś rozliczenia przed tym dniem
        {
          startData = query.Max();
        }

        if (query2.Count() > 0) //są jakieś przychody
        {
          foreach (var pozycje in query2)
          {
            decimal pi = 0; //ilość sztuk przychody
            decimal ri = 0; //ilość sztuk rozchody
            decimal si = 0; //stan na dzień poprzedni

            //ilość sztuk przychody pomiędzy ostatnim rozliczneniem a obecnym włącznie  produktu w cenie pozycji
            var p1 = from c in FormBigEaterCh.Ze.Przychody
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data > startData && c.Data <= stopData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (p1.Count() > 0)
            {
              pi = p1.Sum();
            }

            //ilość sztuk rozchody pomiędzy ostatnim rozliczneniem a obecnym włącznie produktu w cenie pozycji
            var r1 = from c in FormBigEaterCh.Ze.Rozchody
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data > startData && c.Data <= stopData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (r1.Count() > 0)
            {
              ri = r1.Sum();
            }

            //ilość sztuk produktu w cenie pozycji w dniu poprzedzającym
            var s1 = from c in FormBigEaterCh.Ze.DniProdukty
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data == startData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (s1.Count() > 0)
            {
              si = s1.Sum();
            }

            decimal suma = si + pi - ri;

            if (suma != 0 || pi != 0 || ri != 0)
            {
              var dp = new Rozliczenie();
              dp.Grupa = pozycje.GrupyProduktow;
              dp.Nazwa = pozycje.Nazwa;
              dp.Jednostka = pozycje.Jednostka;
              dp.CenaBrutto = pozycje.CenaBrutto;
              dp.IloscOld = si;
              dp.IloscPrz = pi;
              dp.IloscRoz = ri;
              dp.IloscNew = suma;
              lista.Add(dp);
            }
          }
        }
      }

      //}
      //catch( Exception ex)
      //{
      //  MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace);
      //}
    }

    /// <summary>
    /// 
    /// </summary>
    void RefreshDataStanDate(DateTime dt)
    {
      //try
      //{
      FormBigEaterCh.GetDataBase();
      if( FormBigEaterCh.Ze != null )
      {
        var nowe = new List<DniProdukty>();
        //pobieram wszystkie przychody
        var query2 = ( from c in FormBigEaterCh.Ze.Przychody
                       join o in FormBigEaterCh.Ze.Produkty on c.IdProduktu equals o.IdProduktu
                       orderby o.GrupyProduktow orderby o.Nazwa
                       select new
                       {
                         c.IdProduktu,
                         o.GrupyProduktow,
                         o.Nazwa,
                         o.Jednostka,
                         c.CenaBrutto
                       } ).Distinct();


        DateTime? StartData = null;
        DateTime? StopData = dt;

        //szukam daty poprzedniej
        var query = from c in FormBigEaterCh.Ze.DniProdukty
                    where ( c.Data < dt )
                    select c.Data;
        if( query.Count()>0 )      //są jakieś rozliczenia przed tym dniem
        {
          StartData = query.Max();
        }

        if( query2.Count()>0 )      //są jakieś przychody
        {
          foreach( var pozycje in query2 )
          {
            decimal pi = 0; //ilość sztuk przychody
            decimal ri = 0; //ilość sztuk rozchody
            decimal si = 0; //stan na dzień poprzedni

            //ilość sztuk przychody pomiędzy ostatnim rozliczneniem a obecnym włącznie  produktu w cenie pozycji
            var p1 = from c in FormBigEaterCh.Ze.Przychody
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data > StartData && c.Data <= StopData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (p1.Count() > 0)
            {
              pi = p1.Sum();
            }

            //ilość sztuk rozchody pomiędzy ostatnim rozliczneniem a obecnym włącznie produktu w cenie pozycji
            var r1 = from c in FormBigEaterCh.Ze.Rozchody
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data > StartData && c.Data <= StopData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (r1.Count() > 0)
            {
              ri = r1.Sum();
            }

            //ilość sztuk produktu w cenie pozycji w dniu poprzedzającym
            var s1 = from c in FormBigEaterCh.Ze.DniProdukty
                     where
                       (c.IdProduktu == pozycje.IdProduktu && c.Data == StartData &&
                        c.CenaBrutto == pozycje.CenaBrutto)
                     select c.Ilosc;

            if (s1.Count() > 0)
            {
              si = s1.Sum();
            }

            decimal suma = si + pi - ri;

            if (suma != 0 || pi != 0 || ri != 0)
            {
              var dp = FormBigEaterCh.Ze.DniProdukty.CreateObject();
              dp.Data = dt;
              dp.CenaBrutto = pozycje.CenaBrutto;
              dp.IdProduktu = pozycje.IdProduktu;
              dp.Ilosc = suma;
              nowe.Add(dp);
            }
          }
        }


        var oldIds = (from c in FormBigEaterCh.Ze.DniProdukty
                       where ( c.Data == dt )
                       select c.IdDniProdukty).ToList();

        foreach( var i in nowe )
        {

          var oldQuery = from c in FormBigEaterCh.Ze.DniProdukty
                         where (c.Data == dt && c.IdProduktu == i.IdProduktu && c.CenaBrutto==i.CenaBrutto)
                         select c;

          if( oldQuery.Count()>0 )
          {
            foreach( var old in oldQuery )
            {
              old.Ilosc = i.Ilosc;
              oldIds.Remove(old.IdDniProdukty);
            }
          }
          else
          {
            FormBigEaterCh.Ze.AddToDniProdukty(i);
          }
        }

        foreach( var i in oldIds )
        {
          var delQuery = from c in FormBigEaterCh.Ze.DniProdukty
                         where ( c.IdDniProdukty == i )
                         select c;

          foreach (var del in delQuery)
          {
            FormBigEaterCh.Ze.DniProdukty.DeleteObject(del);
          }
        }

      }
     FormBigEaterCh.SaveDataBase();
     FormBigEaterCh.Ze.Refresh(System.Data.Objects.RefreshMode.StoreWins, FormBigEaterCh.Ze.DniProdukty);
      //}
      //catch( Exception ex)
      //{
      //  MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace);
      //}

    }

    /// <summary>
    /// 
    /// </summary>
    private void PrzychodyDataGridViewDefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
    {
      e.Row.Cells["dataColumn"].Value = _activeDay;
    }

    /// <summary>
    /// 
    /// </summary>
    private void RozchodyDataGridViewDefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
    {
      e.Row.Cells["dataColumn1"].Value = _activeDay;
    }

    /// <summary>
    /// 
    /// </summary>
    private void RozliczenieDataGridViewDefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
    {
      e.Row.Cells["dataColumn2"].Value = _activeDay;
    }

    /// <summary>
    /// 
    /// </summary>
    private void przychodyDataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)
    {

    }

    /// <summary>
    /// 
    /// </summary>
    private void przychodyDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {

    }

    /// <summary>
    /// 
    /// </summary>
    private void Button1Click(object sender, EventArgs e)
    {
      var eroz = new FormEditRozchody(_activeDay);
      eroz.ShowDialog();
      RefreshDataRozchody();
      Przelicz();
    }


    /// <summary>
    /// 
    /// </summary>
    private void Button3Click(object sender, EventArgs e)
    {
      FormBigEaterCh.SaveDataBase();
      FormBigEaterCh.Ze.Refresh(System.Data.Objects.RefreshMode.StoreWins, FormBigEaterCh.Ze.Przychody);
      RefreshDataPrzychody();
      RefreshDataRozchody();
      RefreshDataStanDate(_activeDay);
      RefreshDataStan();
      RefreshRozliczenie();
      Przelicz();
    }

    /// <summary>
    /// 
    /// </summary>
    private void Button4Click(object sender, EventArgs e)
    {
      FormBigEaterCh.SaveDataBase();
      FormBigEaterCh.Ze.Refresh(System.Data.Objects.RefreshMode.StoreWins, FormBigEaterCh.Ze.Rozchody);
      RefreshDataPrzychody();
      RefreshDataRozchody();
      RefreshDataStanDate(_activeDay);
      RefreshDataStan();
      RefreshRozliczenie();
      Przelicz();
    }

    /// <summary>
    /// 
    /// </summary>
    private void Button5Click(object sender, EventArgs e)
    {
      FormBigEaterCh.SaveDataBase();
      FormBigEaterCh.Ze.Refresh(System.Data.Objects.RefreshMode.StoreWins, FormBigEaterCh.Ze.Dni);
      RefreshDataPrzychody();
      RefreshDataRozchody();
      RefreshDataStanDate(_activeDay);
      RefreshDataStan();
      RefreshRozliczenie();
      Przelicz();

    }

    /// <summary>
    /// 
    /// </summary>
    private void libreOfficeToolStripMenuItem_Click(object sender, EventArgs e)
    {
      var ofd = new SaveFileDialog
      {
        Filter = @"*.ods|*.ods", DefaultExt = ".ods", AddExtension = true
      };
      ofd.FileName = string.Format("Raport {0}.ods", _activeDay.ToShortDateString());

      if( ofd.ShowDialog()==DialogResult.OK )
      {
        try
        {
          string[] d = new string[] { this.userDzien1.ActiveDay.ToShortDateString(), UserDzien.GetDayName(this.userDzien1.ActiveDay.DayOfWeek), string.Join(", ", this.userDzien1.GetPosilek(EnumPosilek.Sniadanie)), string.Join(", ", this.userDzien1.GetPosilek(EnumPosilek.Obiad)), string.Join(", ", this.userDzien1.GetPosilek(EnumPosilek.Podwieczorek)) };

          var inFile = new Uri(Path.Combine(System.Windows.Forms.Application.StartupPath, "raport.ods"));
          var outFile = new Uri(ofd.FileName);

          var lista = new List<Rozliczenie>();
          RozliczeniePosilki rp = null;

          EksportRozliczenie(_activeDay,lista,out rp);
          RaportExport.CreateRaport(inFile, outFile, d, lista, rp);
        }
        catch( Exception ex )
        {
          MessageBox.Show(ex.Message);
        }
        finally
        {
          MessageBox.Show(@"Eksport zakończono");
          Process.Start(ofd.FileName);
        }
      }
    }

    /// <summary>
    /// 
    /// </summary>
    private void button6_Click(object sender, EventArgs e)
    {
      FormBigEaterCh.Ze.Refresh(System.Data.Objects.RefreshMode.StoreWins, FormBigEaterCh.Ze.Dni);
      RefreshDataPrzychody();
      RefreshDataRozchody();
      RefreshDataStanDate(_activeDay);
      RefreshDataStan();
      RefreshRozliczenie();
      Przelicz();
      var findProc = new Thread(PrzeliczNastępne)
      {
        IsBackground = true
      };
      findProc.Start();
    }

  }
}
